#ifndef __ZHONG_MESSAGE__
#define __ZHONG_MESSAGE__
#include "Factory.hpp"
#include "message.hxx"
#include "message-odb.hxx"

#include<algorithm>

namespace bite_im
{
    class MessageTable
    {
        // using MessagePtr = std::shared_ptr<Message>;
    public:
        using ptr = std::shared_ptr<MessageTable>;
        MessageTable() {}
        MessageTable(const DBPtr &db) : _db(db) {}

        bool insert(Message &message)
        {
            try
            {
                // 获取事务对象，开启事务
                odb::transaction transaction(_db->begin());

                _db->persist(message);
                // 提交事务
                transaction.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERROR("新增消息[{}]出现异常，原因[{}]", message.message_id(), e.what());
                return false;
            }
            return true;
        }
        // 会话结束，删除消息
        bool remove(const std::string &session_id)
        {
            try
            {
                // 获取事务对象，开启事务
                odb::transaction transaction(_db->begin());
                using query = odb::query<Message>;
                _db->erase_query<Message>(query::session_id == session_id);
                // 提交事务
                transaction.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERROR("向会话[{}]删除所有消息失败，原因[{}]", session_id, e.what());
                return false;
            }
            return true;
        }
        // 获取最近的count条消息，需要从后往前遍历
        std::vector<Message> recent(const std::string &session_id, int count)
        {
            std::vector<Message> message_list;
            try
            {
                // 3.获取事务对象，开启事务
                odb::transaction transaction(_db->begin());
                using query = odb::query<Message>;
                using result = odb::result<Message>;
                // 组织sql语句--查询条件

                // 构造condition语句，以当前会话session_id创建时间至今，逆序寻找count个消息
                std::stringstream condition;
                condition << "session_id='" << session_id << "' ";
                condition << "order by create_time desc limit " << count;

                result ret(_db->query<Message>(condition.str()));
                for (auto it = ret.begin(); it != ret.end(); ++it)
                {
                    // it为指向Message的迭代器
                    message_list.push_back(*it);
                }
                // 4.提交事务
                transaction.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERROR("获取会话[{}]中的区间消息失败，原因[{}]", session_id, e.what());
            }
            // 注意返回时，对应信息时间是倒序的，最新消息在数组前
            // 所以最后在外部调用需要逆序
            
            // 进行逆序
            std::reverse(message_list.begin(), message_list.end());
            
            return message_list;
        }
        // 获取一段时间内的所有信息，正常从前往后遍历
        std::vector<Message> range(const std::string &session_id,
                                   const boost::posix_time::ptime &start_time,
                                   const boost::posix_time::ptime &end_time)
        {
            std::vector<Message> message_list;
            try
            {
                // 3.获取事务对象，开启事务
                odb::transaction transaction(_db->begin());
                using query = odb::query<Message>;
                using result = odb::result<Message>;
                // 组织sql语句--查询条件

                result ret(_db->query<Message>(query::session_id == session_id &&
                                               query::create_time >= start_time && query::create_time <= end_time));
                for (auto it = ret.begin(); it != ret.end(); ++it)
                {
                    // it为指向Message的迭代器
                    message_list.push_back(*it);
                }
                // 4.提交事务
                transaction.commit();
            }
            catch (std::exception &e)
            {
                LOG_ERROR("获取会话[{}]中的所有消息失败，原因[{}]", session_id, e.what());
            }
            // 这个接口的message_list是先将离start最近的数据先插入进message_list中
            // 也就是最久的数据放在数组前，这个时候就不用逆序
            return message_list;
        }

    private:
        DBPtr _db;
    };
}

#endif